'''
Created on Apr 22, 2013

@author: Petko
'''
import unittest
from utils.sententialyzer_client import SententialyzerClient
from opinion import checkAttentions,\
    check_opinion_tree
import json


class GetUserOpinionsTest(unittest.TestCase):

    sc = SententialyzerClient()
    
    def setUp(self):
        deleteOpinions=False
        if deleteOpinions:
            self.sc.authorize('moderator1', 'test', 'bopin_r bopin_d')
            result = self.sc.viewListOp('all_base_opinions', 'newest', access_token = self.sc.accessToken)
            page = result['page']
            for op in page:
                self.sc.deleteBaseOp(op['id'])
            
        self.sc.commenterId = 1


    def tearDown(self):
        #result = self.sc.viewListOp('all_base_opinions', 'newest', access_token = self.sc.accessToken)
        #page = result['page']
        
        pass

    
            
    def authAndCreateOp(self, parent, evaluation, **kwargs):
        return self.sc.authAndCreateOp(None, parent, evaluation, **kwargs)
    
    
    def test_get_all_user_opinions(self):
        self.sc.authorize('moderator1', 'test', 'bopin_c')
        
        result = self.sc.createBaseOp("attentions test base", "bla bla bla", "moderators:d sent_default_group:rc")
        
        baseOpId = result['id']
        
        op1 = self.authAndCreateOp(baseOpId, 'positive', title="my comment")
        accessTokenBackup = self.sc.accessToken
        
        #some guys like your comment
        op11 = self.authAndCreateOp(op1['id'], 'positive', title="some guy comment")
        self.authAndCreateOp(op1['id'], 'positive', title="some guy comment")
        
        self.sc.accessToken = accessTokenBackup
        
        #now you comment back some of the guys
        self.sc.createOp(op11['id'], 'neutral', title="comment of guy comment")
        
        #maybe comment yourself
        self.sc.createOp(op1['id'], 'neutral', title="comment of own comment")
        
        checkAttentions(self, baseOpId, 3, 0, 5)
        checkAttentions(self, op1['id'], 2, 0, 4)
        
        result = self.sc.getUserOp(baseOpId, 'most_positive')
        self.assertEqual(result['totalResults'], 3)
        
        #now do something stupid and like the guy opinion
        self.sc.createOp(op11['id'], 'positive')
        checkAttentions(self, baseOpId, 0, 0, 5)
        checkAttentions(self, op1['id'], 3, 0, 4)
        
        result = self.sc.getUserOp(baseOpId, 'most_positive')
        self.assertEqual(result['totalResults'], 4)
        
        #now restore the first opinion
        self.sc.updateOp(op1['id'], evaluation='positive')
        
        checkAttentions(self, baseOpId, 3, 0, 5)
        checkAttentions(self, op1['id'], 2, 0, 4)
        
        result = self.sc.getUserOp(baseOpId, 'most_positive')
        self.assertEqual(result['totalResults'], 3)
    
    def default_check_subopinions_count(self, expected, actual):
        expected_subops_len = len(expected.get('sub_ops', []))
        actual_subops_len = len(actual.get('sub_opinions',[]))
        self.assertEqual(expected_subops_len, actual_subops_len)
        return min(expected_subops_len, actual_subops_len)
    
    def default_check_opinion_id(self, expected, actual):
        self.assertEqual(expected['id'], actual['id'])
        return expected['id'] == actual['id']
    
    def compareTree(self, created_tree, actual_tree, reverse, check_subopinions_count = None, check_opinion_id = None):
        assert isinstance(created_tree, dict)
        assert isinstance(actual_tree, dict)
        
        if not check_subopinions_count:
            check_subopinions_count = self.default_check_subopinions_count
        
        if not check_opinion_id:
            check_opinion_id = self.default_check_opinion_id
        
        if check_opinion_id(created_tree, actual_tree):
            opinionsChecked = 1
            
            subops_len = check_subopinions_count(created_tree, actual_tree)
            
            if subops_len > 0:
                if reverse: 
                    expected_subops = created_tree['sub_ops'][::-1]
                else: 
                    expected_subops = created_tree['sub_ops']
                    
                for i in range(subops_len):
                    opinionsChecked += self.compareTree(expected_subops[i], actual_tree['sub_opinions'][i],
                                                        reverse, check_subopinions_count, check_opinion_id)
            return opinionsChecked
        else:
            return 0
    
    def test_depth_first_list(self):
        
        self.sc.authorize('moderator1', 'test', 'bopin_c')
        
        baseOp = self.sc.createBaseOp("depth_first_list test base", "bla bla bla", "moderators:d sent_default_group:rc")
        
        baseOpId = baseOp['id']
        
        created_tree = []
        
        for i in range(0, 4):
            op1 = self.authAndCreateOp(baseOpId, 'neutral', title="comment " + str(i))
            created_tree.append(op1)
            op1['sub_ops'] = []
            for j in range(0, i):
                op11 = self.authAndCreateOp(op1['id'], ['positive', 'negative'][i % 2], title="some guy comment %d %d" % (i, j))
                
                op1['sub_ops'].append(op11) 
                
                op11['sub_ops'] = []
                
                o = self.authAndCreateOp(op11['id'], 'positive', title="some guy comment %d %d 1" % (i, j))
                
                op11['sub_ops'].append(o)
                
                o = self.authAndCreateOp(op11['id'], ['positive', 'negative'][j % 2], title="some guy comment %d %d 2" % (i, j))
                
                op11['sub_ops'].append(o)
        
        baseOp['sub_ops'] = created_tree
        
        #don't do this in real situation - it's dummy
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'most_positive',
                                             'max_depth': 1,
                                             'subopinions_desc': {'tree_order': 'depth_first',
                                                                  'order': 'most_positive',
                                                                  'max_depth': 1,
                                                                  'subopinions_desc': {'tree_order': 'flat',
                                                                                      'order': 'most_positive',
                                                                                      'max_depth': 1
                                                                                      }
                                                                  }
                                             })
        
        self.assertEqual(result['total'], 6 * 3 + 4)
        
        self.assertEqual(result['sub_opinions'][0]['id'], created_tree[2]['id'])
        self.assertEqual(result['sub_opinions'][0]['positive'], 5)
        
        self.assertEqual(result['sub_opinions'][1]['id'], created_tree[3]['id'])
        self.assertEqual(result['sub_opinions'][1]['positive'], 1)
        
        self.assertEqual(result['sub_opinions'][0]['sub_opinions'][0]['id'], created_tree[2]['sub_ops'][0]['id'])
        self.assertEqual(result['sub_opinions'][0]['sub_opinions'][1]['id'], created_tree[2]['sub_ops'][1]['id'])
        
        self.assertEqual(result['sub_opinions'][1]['sub_opinions'][0]['total'], 2)
        actual_subops = result['sub_opinions'][1]['sub_opinions'][0]['sub_opinions']
        self.assertEqual(len(actual_subops), 2)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'oldest',
                                             'max_depth': 5,
                                             'max_subopinions': 6 * 3 + 4})
        #print json.dumps(result)
        
        test_result = self.compareTree(baseOp, result, False)
        
        #test the test - testseption?
        self.assertEqual(test_result, 6 * 3 + 5)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'newest',
                                             'max_depth': 5,
                                             'max_subopinions': 6 * 3 + 4})
        #print json.dumps(result)
        
        self.assertEqual(self.compareTree(baseOp, result, True), 6 * 3 + 5)
        
        #like some more this one so it is unique by positive attention
        o = self.authAndCreateOp(created_tree[1]['id'], 'positive')
        #created_tree[1]['sub_ops'].append(o)
        
        o = self.authAndCreateOp(created_tree[1]['id'], 'positive')
        #created_tree[1]['sub_ops'].append(o)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'oldest',
                                             'max_depth': 5,
                                             'max_subopinions': 6 * 3 + 6})
        #print json.dumps(result)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'most_positive',
                                             'max_depth': 1,
                                             'subopinions_desc': {'tree_order': 'depth_first',
                                                                  'order': 'newest',
                                                                  'max_depth': 5,
                                                                  'max_subopinions': 6 * 3 + 4,
                                                                  'skip_empty': 0}
                                             })
        
        self.assertEqual(self.compareTree(created_tree[2], result['sub_opinions'][0], True), 7)
        
        self.assertEqual(self.compareTree(created_tree[1], result['sub_opinions'][1], True), 4)
        self.assertEqual(result['sub_opinions'][1]['positive'], 2)
        
        self.assertEqual(self.compareTree(created_tree[3], result['sub_opinions'][2], True), 10)
        
        self.assertEqual(self.compareTree(created_tree[0], result['sub_opinions'][3], True), 1)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'most_positive',
                                             'max_depth': 1,
                                             'subopinions_desc': {'tree_order': 'depth_first',
                                                                  'order': 'newest',
                                                                  'max_depth': 5,
                                                                  'max_subopinions': 5,
                                                                  'skip_empty': 0}
                                             })
        
        self.assertEqual(self.compareTree(created_tree[1], result['sub_opinions'][1], True), 4)
        self.assertEqual(self.compareTree(created_tree[0], result['sub_opinions'][3], True), 1)
        
        def no_check_subopinions_count(expected, actual):
            expected_subops_len = len(expected.get('sub_ops', []))
            actual_subops_len = len(actual.get('sub_opinions',[]))
            return min(expected_subops_len, actual_subops_len)

        self.assertEqual(self.compareTree(created_tree[2], result['sub_opinions'][0], True, check_subopinions_count = no_check_subopinions_count), 6)
        self.assertEqual(self.compareTree(created_tree[3], result['sub_opinions'][2], True, check_subopinions_count = no_check_subopinions_count), 6)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'oldest',
                                             'max_depth': 1,
                                             'max_subopinions': 4})
        
        def check_subopinions_count_0(expected, actual):
            expected_subops_len = len(expected.get('sub_ops', []))
            actual_subops_len = len(actual.get('sub_opinions',[]))
            self.assertEqual(actual_subops_len, 0)
            return min(expected_subops_len, actual_subops_len)
        
        self.assertEqual(self.compareTree(created_tree[0], result['sub_opinions'][0], False, check_subopinions_count = check_subopinions_count_0), 1)
        self.assertEqual(self.compareTree(created_tree[1], result['sub_opinions'][1], False, check_subopinions_count = check_subopinions_count_0), 1)
        self.assertEqual(self.compareTree(created_tree[2], result['sub_opinions'][2], False, check_subopinions_count = check_subopinions_count_0), 1)
        self.assertEqual(self.compareTree(created_tree[3], result['sub_opinions'][3], False, check_subopinions_count = check_subopinions_count_0), 1)
        
        #add some positive opinions here (since there are 3 negative subopinions) so that we can check they are correctly ordered by evaluation
        o = self.authAndCreateOp(created_tree[3]['id'], 'positive', title='xxx')
        created_tree[3]['sub_ops'].append(o)
        
        o = self.authAndCreateOp(created_tree[3]['id'], 'positive', title="additional positive comment")
        created_tree[3]['sub_ops'].append(o)
        
        o1 = self.authAndCreateOp(o['id'], 'positive', title='yyy')
        o['sub_ops'] = []
        o['sub_ops'].append(o1)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'oldest',
                                             'max_depth': 5,
                                             'max_subopinions': 6 * 3 + 9})
        print json.dumps(result)
        
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'most_positive',
                                             'max_depth': 1,
                                             'subopinions_desc': {'tree_order': 'breadth_first',
                                                                  'evaluation_order': 'positive',
                                                                  'order': 'most_positive',
                                                                  'max_depth': 5,
                                                                  'max_subopinions': 5,
                                                                  'order_hierarchically': 0,
                                                                  'skip_empty': 0}
                                             })
        
        print json.dumps(result)
        
        self.assertEqual(created_tree[0]['id'], result['sub_opinions'][3]['id'])
        self.assertEqual(created_tree[1]['id'], result['sub_opinions'][2]['id'])
        self.assertEqual(created_tree[2]['id'], result['sub_opinions'][0]['id'])
        self.assertEqual(created_tree[3]['id'], result['sub_opinions'][1]['id'])
        
        self.assertEqual(0, len(result['sub_opinions'][3]['sub_opinions']))
        self.assertEqual(3, len(result['sub_opinions'][2]['sub_opinions']))
        self.assertEqual(5, len(result['sub_opinions'][0]['sub_opinions']))
        self.assertEqual(5, len(result['sub_opinions'][1]['sub_opinions']))
        
        self.assertEqual(created_tree[3]['sub_ops'][4]['id'], result['sub_opinions'][1]['sub_opinions'][0]['id'])
        self.assertEqual(created_tree[3]['sub_ops'][3]['id'], result['sub_opinions'][1]['sub_opinions'][1]['id'])
        self.assertEqual(created_tree[3]['sub_ops'][1]['id'], result['sub_opinions'][1]['sub_opinions'][4]['id'])
        
        #test optimization when the max_subopinions is greater than the number of subopinions
        result = self.sc.getOpExt(baseOpId, {'tree_order': 'depth_first',
                                             'order': 'most_positive',
                                             'max_depth': 1,
                                             'subopinions_desc': {'tree_order': 'breadth_first',
                                                                  'evaluation_order': 'positive',
                                                                  'order': 'most_positive',
                                                                  'max_depth': 5,
                                                                  'max_subopinions': 15,
                                                                  'order_hierarchically': 0,
                                                                  'skip_empty': 0}
                                             })
        
        self.assertEqual(12, len(result['sub_opinions'][1]['sub_opinions']))
        
        print json.dumps(result['sub_opinions'][1])
        
        self.assertEqual(created_tree[3]['sub_ops'][4]['id'], result['sub_opinions'][1]['sub_opinions'][0]['id'])
        self.assertEqual(created_tree[3]['sub_ops'][3]['id'], result['sub_opinions'][1]['sub_opinions'][1]['id'])
        self.assertEqual(created_tree[3]['sub_ops'][1]['id'], result['sub_opinions'][1]['sub_opinions'][4]['id'])
        
        check_opinion_tree(self, baseOpId)
        
        print "done"
    
    def test_skip_empty(self):
        self.sc.authorize('moderator1', 'test', 'bopin_c')
        
        baseOp = self.sc.createBaseOp("skip_empty test base", "bla bla bla", "moderators:d sent_default_group:rc")
        
        self.authAndCreateOp(baseOp['id'], 'positive', title="additional positive comment")
        o = self.authAndCreateOp(baseOp['id'], 'positive', title="additional positive comment 1")
        self.authAndCreateOp(baseOp['id'], 'positive')
        
        self.authAndCreateOp(o['id'], 'positive', title="additional positive comment 1 1")
        self.authAndCreateOp(o['id'], 'positive')
        
        result = self.sc.getOpSimple(baseOp['id'], 'most_attended', max_content_length=20, tree_order="flat", max_subopinions=20, skip_empty=1)
        
        self.assertEqual(3, len(result['sub_opinions']))
        
        self.assertEqual(o['id'], result['sub_opinions'][0]['id'])
    
    def test_multilevel_depth_first(self):
        self.sc.authorize('moderator1', 'test', 'bopin_c')
        
        baseOp = self.sc.createBaseOp("depth first test", "bla bla bla", "moderators:d sent_default_group:rc")
        
        o = self.authAndCreateOp(baseOp['id'], 'positive', title="1")
        
        self.authAndCreateOp(o['id'], 'positive', title="1.1")
        
        result = self.sc.getOpExt(baseOp['id'], {'tree_order': 'depth_first',
                                             'order': 'oldest',
                                             'max_depth': 3,
                                             'max_subopinions': 1,
                                             'first_subopinion': 1
                                             })
        
        #The opinion with index 1 is 1.1 but its parent(s) must also be returned
        self.assertEqual(result['sub_opinions'][0]['title'], '1')
        
        self.assertEqual(result['sub_opinions'][0]['sub_opinions'][0]['title'], '1.1')
    
    
        
    def test_check_opinion_consistency(self):
        self.sc.authorize('moderator1', 'test', 'bopin_c')
        
        #baseOpId = "00000000-0000-0000-0000-00000000005e"
        #baseOpId = "00000000-0000-0000-0000-00000000006a"
        #baseOpId = "00000000-0000-0000-0000-000000000083"
        #baseOpId = "00000000-0000-0000-0000-00000000000e"
        
        #check_opinion_tree(self, baseOpId)
        
        
if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()
